﻿using System;
using System.Net;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using GalaSoft.MvvmLight.Messaging;
using System.Linq;
using JustinAngel.Neurons.Services;

namespace JustinAngel.Neurons.Framework.AppSpecific
{
    public static class Initializer
    {
        private static bool _isInitialized = false;

        public static void Init()
        {
            if (!_isInitialized)
            {
                _isInitialized = true; 

                InitIoC();

                InitServices();
            }

        }

        private static void InitServices()
        {
            var allAppServices = AllAssemblies.SelectMany(a =>
                    a.GetTypes().Where(t => t.GetInterfaces().Contains(typeof(IAppService))));

            foreach (var appService in allAppServices)
            {
                IAppService service = (IAppService)IoC.Get(appService);
                service.StartService();
            }
        }

        private static Assembly[] AllAssemblies =
            new Assembly[] 
            {  
                typeof(MainPage).Assembly
            };

        private static void InitIoC()
        {
            IoC.Register<IMessenger>(Messenger.Default);
            AutoInitIoCForInterfacesWithOneSetupIn(AllAssemblies, typeof(IDataService));
            IoC.Register<IDataService>(new DataService());
        }

        private static void AutoInitIoCForInterfacesWithOneSetupIn(Assembly[] assemblies, params Type[] excludedInterfaces)
        {
            var AllInterfaces = assemblies.SelectMany(a => a.GetTypes().Where(t => t.IsInterface))
                                          .Where(t => !excludedInterfaces.Any(ex => ex.FullName == t.FullName));
            var AllTypes = assemblies.SelectMany(a => a.GetTypes().Where(t => !t.IsInterface));
            foreach (var interfaceToCheckIfHasJust1Implementor in AllInterfaces)
            {
                var TypesThatImplementInterface =
                    AllTypes.Where(t => t.GetInterfaces().Contains(interfaceToCheckIfHasJust1Implementor));
                if (TypesThatImplementInterface.Count() == 1)
                {
                    if (!IoC.IsRegistered(interfaceToCheckIfHasJust1Implementor))
                    {
                        IoC.Register(interfaceToCheckIfHasJust1Implementor, TypesThatImplementInterface.Single());
                    }
                }
            }
        }
    }
}
